package rpcclient

import (
	"context"
	"fmt"
	"gitee.com/851537/gbase"
	rpcbase "gitee.com/851537/gpkg/rpc/base"
	"github.com/pkg/errors"
	"github.com/smallnest/rpcx/client"
	"reflect"
)

type Client struct {
	//服务端地址，必须，fmt ip:port
	addr string

	//密钥
	secKey string

	//服务名,必须
	service string

	//一个XCLinet只对一个服务负责，它可以通过serviceMethod参数来调用这个服务的所有方法。如果你想调用多个服务，你必须为每个服务创建一个XClient。
	xClient client.XClient
}

func (this *Client) GetKey() string {
	return fmt.Sprintf("%s:%s", this.addr, this.service)
}

func (this *Client) vd() error {
	if this.addr == "" {
		return errors.New("rpc client addr is empty")
	} else if this.service == "" {
		return errors.New("rpc client service is empty")
	}
	return nil
}

func (this *Client) Call(method string, req any, resp any) error {
	return this.xClient.Call(context.Background(), method, req, resp)
}

func (client *Client) Close() error {
	return client.xClient.Close()
}

func NewClient(opts ...gbase.Option[*Client]) (obj *Client, err error) {
	obj = &Client{}
	for _, v := range opts {
		v(obj)
	}

	if err = obj.vd(); err != nil {
		return nil, err
	}
	//初始化xClient
	d, err := client.NewPeer2PeerDiscovery(fmt.Sprintf("tcp@%s", obj.addr), "")
	if err != nil {
		return nil, err
	}
	obj.xClient = client.NewXClient(obj.service, client.Failtry, client.RandomSelect, d, client.DefaultOption)

	if obj.secKey != "" {
		obj.xClient.Auth(rpcbase.NewTokenWithMd5(obj.secKey).ToString())
	}

	//clients.Store(obj.GetKey(), obj)
	return
}

func WithAddr(addr string) gbase.Option[*Client] {
	return func(obj *Client) {
		obj.addr = addr
	}
}

func WithSecKey(secKey string) gbase.Option[*Client] {
	return func(obj *Client) {
		obj.secKey = secKey
	}
}

func WithService(service any) gbase.Option[*Client] {
	return func(obj *Client) {
		serviceType := reflect.TypeOf(service)
		switch serviceType.Kind() {
		case reflect.String:
			obj.service = service.(string)
		case reflect.Ptr:
			obj.service = serviceType.Elem().Name()
		default:
			obj.service = serviceType.Name()
		}
	}
}
